package com.siteseat.common.security;

import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

import org.apache.commons.lang3.StringUtils;

public class Credential {

  private String                       name;

  private String                       password;

  private byte[]                       encryptionKey;

  private Map<String, Set<Permission>>     permissions = new HashMap<String, Set<Permission>>();

  private boolean                      administrator;
  
  private Map<String,Object>  salt = new HashMap<String,Object>();

  public Credential() {
    
  }
  
  /**
   * @param name
   */
  public Credential( String name, boolean administrator ) {
    this.name = name;
    this.administrator = administrator;
  }
  
  

  /**
   * Gets the salt
   *
   * @return the salt
   */
  public Object getSalt( String key ) {
    return salt.get( key );
  }

  /**
   * Sets the salt
   *
   * @param salt the salt to set
   */
  public void setSalt( String key, Object salt ) {
    this.salt.put( key, salt );
  }

  /**
   * Gets the administrator
   * 
   * @return the administrator
   */
  public boolean isAdministrator() {
    return administrator;
  }

  /**
   * 
   */
  public void validate() throws SecurityException {
    if( StringUtils.isBlank( getName() ) ) {
      throw new SecurityException( "Name cannot be blank" );
    }
    
    if( isAdministrator() == false ) {
      if( StringUtils.isBlank( getPassword() ) ) {
        throw new SecurityException( "Password cannot be blank" );
      }
      //if( encryptionKey == null || encryptionKey.length == 0 ) {
      //  throw new SecurityException( "encryptionKey cannot be blank" );
      //}
    }
  }

  /**
   * @param resource
   * @param permission
   */
  public void grantPermission( String resource, Permission permission ) {
    Set<Permission> p = this.permissions.get( resource );
    if( p == null ) {
      p = new HashSet<Permission>();
      this.permissions.put( resource, p );
    }

    p.add( permission );
  }

  /**
   * @param permission
   */
  public void revokePermission( String resource, Permission permission ) {
    Set<Permission> p = this.permissions.get( resource );
    if( p != null ) {
      p.remove( permission );
    }
  }

  /**
   * @param resource
   * @param permission
   * @return
   */
  public boolean hasPermission( String resource, Permission permission ) {
    Set<Permission> p = this.permissions.get( resource );
    if( p == null ) {
      return false;
    }
    return p.contains( permission );
  }

  /**
   * Gets the userName
   * 
   * @return the userName
   */
  public String getName() {
    return name;
  }

  /**
   * Gets the password
   * 
   * @return the password
   */
  public String getPassword() {
    return password;
  }

  /**
   * Sets the password
   * 
   * @param password
   *          the password to set
   */
  public void setPassword( String password ) {
    this.password = password;
  }

  /**
   * Gets the encryptionKey
   * 
   * @return the encryptionKey
   */
  public byte[] getEncryptionKey() {
    return encryptionKey;
  }

  /**
   * Sets the encryptionKey
   * 
   * @param encryptionKey
   *          the encryptionKey to set
   */
  public void setEncryptionKey( byte[] encryptionKey ) {
    this.encryptionKey = encryptionKey;
  }

  /**
   * Gets the permissions
   *
   * @return the permissions
   */
  public Map<String, Set<Permission>> getPermissions() {
    return permissions;
  }
  
  /**
   * Sets the permissions
   *
   * @param p the permissions to set
   */
  public void setPermissions( Map<String, Permission[]> ps ) {
    permissions.clear();
    
    for( Map.Entry<String, Permission[]> p: ps.entrySet() ) {
      Permission[] as = p.getValue();
      Set<Permission> t = new HashSet<Permission>( as.length );
      for( Permission a: as ) {
        t.add( a );
      }
      this.permissions.put( p.getKey(), t );
    }
  }

  /**
   * Sets the name
   *
   * @param name the name to set
   */
  public void setName( String name ) {
    this.name = name;
  }

  /**
   * Sets the administrator
   *
   * @param administrator the administrator to set
   */
  public void setAdministrator( boolean administrator ) {
    this.administrator = administrator;
  }

  /**
   * {@inheritDoc}
   */
  @Override
  public String toString() {
    return "Credential [name=" + name + "]";
  }

}
